package main.java.com.rmisorter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;

@SuppressWarnings({"rawtypes", "unused", "unchecked"})
public class ListHandler {

	private int generateRandomInteger() {
		Random r = new Random();
		return (int) r.nextInt();
	}
	
	private String generateRandomString() {
		int i;
		char[] randomWord = new char[(int) (Math.random() * 10) + 5];
		Random r = new Random();
		
		for (i = 0; i < randomWord.length; i++) {
			randomWord[i] = (char) (65 + r.nextInt(26));
		}
		
		return new String(randomWord);
	}
	
	private Comparable generateRandomPerson() {
		return new Person(generateRandomString(), generateRandomInteger());
	}
	
	Comparable[] generateRandomList(int length, String method) throws Exception {
		int i = 0;
		Method generateMethod;
		Comparable[] list = new Comparable[length];
		
		for (i = 0; i < length; i++) {
			generateMethod = this.getClass().getDeclaredMethod(method);
			list[i] = (Comparable) generateMethod.invoke(this);	
		}
		
		return list;
	}

	Comparable[][] splice(Comparable[] listToSplice, int numberOfLists) {
		Comparable[][] comparableLists = new Comparable[numberOfLists][];
		Comparable[] pivots = getSortedPivots(listToSplice, numberOfLists);
		
		comparableLists = handleLists(listToSplice, pivots);

		return comparableLists;
	}

	private Comparable[][] handleLists(Comparable[] listToSplice, Comparable[] pivots) {
		ArrayList<ArrayList<Comparable>> lists = new ArrayList<ArrayList<Comparable>>();
		lists = createLists(pivots.length);
		ArrayList<Comparable> arrayListToSplice = convertArrayToArrayList(listToSplice);
		int i, j, largest;
		
		for (i = 0; i < arrayListToSplice.size(); i++) {
			for (j = 1; j <= pivots.length; j++) {
				if (arrayListToSplice.get(i).compareTo(pivots[j-1]) <= 0) {
					lists.get(j-1).add(arrayListToSplice.get(i));
					arrayListToSplice.remove(i);
					i--;
					j = pivots.length+1;
				}
			}
		}
		lists.get(lists.size() - 1).addAll(arrayListToSplice);

		return convertArrayListToArray(lists);

	}
	
	private ArrayList<ArrayList<Comparable>> createLists(int numberOfLists) {
		ArrayList<ArrayList<Comparable>> lists = new ArrayList<ArrayList<Comparable>>();
		int i;
		
		for (i = 0; i < numberOfLists; i++) {
			ArrayList<Comparable> subList = new ArrayList<Comparable>();
			lists.add(subList);
		}
		
		return lists;
	}
	
	private ArrayList<Comparable> convertArrayToArrayList(Comparable[] list) {
		int i = 0;
		ArrayList<Comparable> arrayList = new ArrayList<Comparable>();
		for (i = 0; i < list.length; i++) {
			arrayList.add(list[i]);
		}
		return arrayList;
	}
	
	private Comparable[][] convertArrayListToArray(ArrayList<ArrayList<Comparable>> arrayListToConvert) {
		int i = 0;
		Comparable[][] convertedList = new Comparable[arrayListToConvert.size()][];
		
		for (i = 0; i < arrayListToConvert.size(); i++) {
			convertedList[i] = arrayListToConvert.get(i).toArray(new Comparable[arrayListToConvert.get(i).size()]);
		}
		
		return convertedList;
		
	}
	
	
	private Comparable[] getSortedPivots(Comparable[] listToSort, int numberOfLists) {
		Comparable[] pivots = new Comparable[numberOfLists];
		double pivot = (listToSort.length / numberOfLists);
		Comparable item;
		int i = 0;
		Random r;
		
		while (i < numberOfLists) {
			item = listToSort[(int) (((i+1) * pivot) - 1)];
			
			if (isUniquePivot(pivots, item)) {
				pivots[i] = item;
				i++;
			}
		}
		
		Arrays.sort(pivots);

		return pivots;
	}
	
	private boolean isUniquePivot(Comparable[] pivots, Comparable pivot) {
		int i;
		for (i = 0; i < pivots.length; i++) {
			if (pivots[i] != null) {
				if (pivots[i].compareTo(pivot) == 0) {
					return false;
				}
			}
		}
		
		return true;
	}

}
